package com.seed.uaa.tenant.web;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.query.QueryChain;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.update.UpdateChain;
import com.seed.application.service.BaseService;
import com.seed.core.pojo.Const;
import com.seed.core.pojo.SetDTO;
import com.seed.uaa.pojo.RoleAction;
import com.seed.uaa.pojo.TenantAction;
import com.seed.uaa.util.EncryptUtil;
import com.seed.uaa.util.PermiUtil;
import com.seed.uaa.web.UaaService;
import com.seed.uaa.web.role.Role;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static com.seed.uaa.tenant.web.table.TenantRoleTableDef.TENANT_ROLE;
import static com.seed.uaa.tenant.web.table.TenantTableDef.TENANT;
import static com.seed.uaa.web.role.table.RoleTableDef.ROLE;

@Service
public class TenantService extends BaseService<TenantMapper, Tenant> {

    public TenantService() {
        super(Tenant.class);
    }

    @Transactional
    public boolean save(Tenant tenant) {
        String tenantname = tenant.getTenantname();
        if(StrUtil.isBlank(tenantname)) throw new RuntimeException("租户名不能为空");

//        DDLManager.run(AppManager.getApp(), tenantname); TODO
        return super.save(tenant);
    }

    public boolean resetPassword(String id) {
        Tenant tenant = getById(id);
        if(tenant == null) throw new RuntimeException("数据不存在");

        String salt = UUID.fastUUID().toString();
        String encrypt = EncryptUtil.encrypt(Const.INIT_PASSWORD_VALUE, salt);
        tenant.setPassword(encrypt);
        tenant.setSalt(salt);
        return update(tenant);
    }

//    @Override
//    public boolean setTenantname(String id, String value) {
//        Tenant tenant = getById(id);
//        if(tenant == null) throw new RuntimeException("数据不存在");
//
//        if(value.equals(tenant.getTenantname())) return true;
//
//        String tenantname = value;
//        List<Tenant> tenants = list(query().where(TENANT.TENANTNAME.eq(tenantname)).and(TENANT.ID.ne(id)));
//        if(!tenants.isEmpty()) {
//            throw new RuntimeException(String.format("账号【%s】已存在", tenantname));
//        }
//
//        String rawPassword = "123456";
//        String salt = UUID.fastUUID().toString();
//        String encrypt = EncryptUtil.encrypt(rawPassword, salt);
//        return UpdateChain.of(Tenant.class)
//                .set(Tenant::getTenantname, tenantname)
//                .set(User::getPassword, encrypt)
//                .set(User::getSalt, salt)
//                .where(TENANT.ID.eq(id))
//                .update();
//    }

//    @Override
//    public boolean reset(String id) {
//        Tenant tenant = getById(id);
//        if(tenant == null) throw new RuntimeException("数据不存在");
//
//        String rawPassword = "123456";
//        String salt = UUID.fastUUID().toString();
//        String encrypt = EncryptUtil.encrypt(rawPassword, salt);
//        return UpdateChain.of(Tenant.class)
//                .set(Tenant::getPassword, encrypt)
//                .set(Tenant::getSalt, salt)
//                .where(TENANT.ID.eq(id))
//                .update();
//    }

//    @Override
//    public boolean setExpireDate(String id, String value) {
//        Tenant tenant = getById(id);
//        if(tenant == null) throw new RuntimeException("数据不存在");
//        LocalDateTime expireDate = StrUtil.isBlank(value) ? null : DateUtil.parseLocalDateTime(value + " 23:59:59");
//        return UpdateChain.of(User.class)
//                .set(User::getExpireDate, expireDate)
//                .where(USER.ID.eq(id))
//                .update();
//    }

//    @Override
//    public boolean setUsable(String id, YesNo value, String reason) {
//        Tenant tenant = getById(id);
//        if(tenant == null) throw new RuntimeException("数据不存在");
//
//        return UpdateChain.of(Tenant.class)
//                .set(Tenant::getUsable, value)
//                .set(Tenant::getReason, reason)
//                .where(TENANT.ID.eq(id))
//                .update();
//    }
//
//    @Override
//    public boolean setLoginable(String id, YesNo value, String reason) {
//        Tenant tenant = getById(id);
//        if(tenant == null) throw new RuntimeException("数据不存在");
//
//        return UpdateChain.of(Tenant.class)
//                .set(Tenant::getLoginable, value)
//                .set(Tenant::getReason, reason)
//                .where(TENANT.ID.eq(id))
//                .update();
//    }
//
//    @Override
//    public boolean setEnable(String id, YesNo value, String reason) {
//        Tenant tenant = getById(id);
//        if(tenant == null) throw new RuntimeException("数据不存在");
//
//        return UpdateChain.of(Tenant.class)
//                .set(Tenant::getEnable, value)
//                .set(Tenant::getReason, reason)
//                .where(TENANT.ID.eq(id))
//                .update();
//    }

//    @Override
//    public boolean active(String id) {
//        Tenant tenant = getById(id);
//        if(tenant == null) throw new RuntimeException("数据不存在");
//        if(YesNo.yes.equals(tenant.getActive())) return true;
//
//        return UpdateChain.of(Tenant.class)
//                .set(Tenant::getActive, YesNo.yes)
//                .where(TENANT.ID.eq(id))
//                .update();
//    }

    public boolean setDb(Tenant value) {
        Tenant tenant = getById(value.getId());
        if(tenant == null) throw new RuntimeException("数据不存在");

        String dbUrl = value.getDbUrl();
        if(StrUtil.isBlank(dbUrl)) throw new RuntimeException("数据库连接不能为空");

        String dbUsername = value.getDbUsername();
        if(StrUtil.isBlank(dbUsername)) throw new RuntimeException("数据库账号不能为空");

        String dbPassword = value.getDbPassword();

        return UpdateChain.of(Tenant.class)
                .set(Tenant::getDbUrl, dbUrl)
                .set(Tenant::getDbUsername, dbUsername)
                .set(Tenant::getDbPassword, dbPassword)
                .where(TENANT.ID.eq(value.getId()))
                .update();
    }

//    public List<String> getRoles(String id) {
//        QueryWrapper qw = query().where(TENANT_ROLE.TENANT_ID.eq(id));
//        return tenantRoleMapper.selectListByQuery(qw).stream().map(TenantRole::getRoleId).toList();
//    }
//
//    @Override
//    @Transactional
//    public boolean setRoles(String id, String value) {
//        Tenant tenant = getById(id);
//        if(tenant == null) throw new RuntimeException("数据不存在");
//
//        UpdateChain.of(TenantRole.class).where(TENANT_ROLE.TENANT_ID.eq(id)).remove();
//        if(StrUtil.isNotBlank(value)) {
//            List<TenantRole> tenantRoles = Stream.of(value.split(","))
//                    .map(roleId -> {
//                        TenantRole ret = new TenantRole();
//                        ret.setTenantId(id);
//                        ret.setRoleId(roleId.trim());
//                        return ret;
//                    }).toList();
//            tenantRoleMapper.insertBatch(tenantRoles);
//        }
//        return true;
//    }

//    public OwnerAction getOwnerAction(String id) {
//        return uaaService.getOwnerAction(PermiOwner.organization, id);
//    }

    public List<String> getActions(String id) {
        QueryWrapper queryWrapper = query()
                .select(TENANT.ID, TENANT.ACTIONS)
                .where(TENANT.ID.eq(id));

        Tenant tenant = getMapper().selectOneByQuery(queryWrapper);
        if(tenant == null) throw new RuntimeException("数据不存在");

        String actions = tenant.getActions();
        if(StrUtil.isBlank(actions)) return Collections.emptyList();

        return List.of(actions.split(","));
    }

    @Transactional
    public boolean setActions(SetDTO dto) {
        String id = dto.getId();
        Tenant tenant = one(id);
        if(tenant == null) throw new RuntimeException("数据不存在");

        String value = dto.getValue();
        tenant.setActions(value);
        return getMapper().update(tenant) > 0;
    }

    public List<String> getDatas(String id, String actionPath) {
        QueryWrapper queryWrapper = query()
                .select(TENANT.ID, TENANT.DATAS)
                .where(TENANT.ID.eq(id));

        Tenant tenant = getMapper().selectOneByQuery(queryWrapper);
        if(tenant == null) throw new RuntimeException("数据不存在");

        String datas = tenant.getDatas();
        if(StrUtil.isBlank(datas)) return Collections.emptyList();

        return PermiUtil.extract(datas, actionPath);
    }

    public boolean setDatas(String id, String actionPath, List<String> operates) {
        QueryWrapper queryWrapper = query()
                .select(TENANT.ID, TENANT.DATAS, TENANT.VERSION)
                .where(TENANT.ID.eq(id));

        Tenant tenant = getMapper().selectOneByQuery(queryWrapper);
        if(tenant == null) throw new RuntimeException("数据不存在");

        tenant.setDatas(PermiUtil.edit(tenant.getDatas(), actionPath, operates));
        return getMapper().update(tenant) > 0;
    }

    public List<String> getFields(String id, String actionPath) {
        QueryWrapper queryWrapper = query()
                .select(TENANT.ID, TENANT.FIELDS)
                .where(TENANT.ID.eq(id));

        Tenant tenant = getMapper().selectOneByQuery(queryWrapper);
        if(tenant == null) throw new RuntimeException("数据不存在");

        String fields = tenant.getFields();
        if(StrUtil.isBlank(fields)) return Collections.emptyList();

        return PermiUtil.extract(fields, actionPath);
    }

    public boolean setFields(String id, String actionPath, List<String> operates) {
        QueryWrapper queryWrapper = query()
                .select(TENANT.ID, TENANT.FIELDS, TENANT.VERSION)
                .where(TENANT.ID.eq(id));

        Tenant tenant = getMapper().selectOneByQuery(queryWrapper);
        if(tenant == null) throw new RuntimeException("数据不存在");

        tenant.setFields(PermiUtil.edit(tenant.getFields(), actionPath, operates));
        return getMapper().update(tenant) > 0;
    }

    private Tenant one(String id) {
        QueryWrapper queryWrapper = query()
                .select(TENANT.ID, TENANT.VERSION)
                .where(TENANT.ID.eq(id));
        return getMapper().selectOneByQuery(queryWrapper);
    }

    public TenantAction getTenantAction(String id) {
        Tenant tenant = QueryChain.of(Tenant.class)
                .select(TENANT.ID, TENANT.NAME, TENANT.ACTIONS)
                .where(TENANT.ID.eq(id))
                .one();
        if(tenant == null) throw new RuntimeException("数据不存在");

        TenantAction ret = new TenantAction(id, tenant.getName());
        String actions = tenant.getActions();
        if(StrUtil.isNotBlank(actions)) {
            ret.setActions(List.of(actions.split(",")));
        }

//        String organizationId = user.getOrganizationId();
//        if(StrUtil.isNotBlank(organizationId)) {
//            ret.setOrganizationAction(getOrganizationAction(organizationId));
//        }
        List<RoleAction> roleActions = new ArrayList<>();
        List<Role> roles = QueryChain.of(Role.class)
                .select(ROLE.ID, ROLE.NAME)
                .innerJoin(TENANT_ROLE).on(TENANT_ROLE.TENANT_ID.eq(id))
                .list();

        for(Role role: roles) {
            RoleAction roleAction = new RoleAction(role.getId(), role.getName());
            String actions1 = role.getActions();
            if(StrUtil.isNotBlank(actions1)) {
                roleAction.setActions(List.of(actions1.split(",")));
                roleActions.add(roleAction);
            }
        }
        ret.setRoleActions(roleActions);

        return ret;
    }

//    public String getDataSourceKey(Tenant tenant) {
//        AppPath appPath = AppKey.get();
//        String microPath = appPath.microKey();
//        String key = microPath + '.' + tenant.getTenantname();
//        Map<String, DataSource> dataSourceMap = FlexGlobalConfig.getDefaultConfig().getDataSource().getDataSourceMap();
//        DataSource dataSource = dataSourceMap.get(key);
//        if(dataSource == null) {
//            // 加载数据源
//            FlexDataSource flexDataSource = FlexGlobalConfig.getDefaultConfig().getDataSource();
//            HikariDataSource newDataSource = getTenantDataSource(tenant);
//
//            flexDataSource.addDataSource(key, newDataSource);
//            DataSourceKey.use(key, () -> UaaDDL.createTables(tenant.getTenantname()));
//        }
//
//        return key;
//    }

//    public String createDatabase(String key) {
////        AppPath appPath = AppKey.get();
////        String microPath = appPath.microKey();
////        String key = microPath + '.' + tenant.getTenantname();
//        Map<String, DataSource> dataSourceMap = FlexGlobalConfig.getDefaultConfig().getDataSource().getDataSourceMap();
//        DataSource dataSource = dataSourceMap.get(key);
//        if(dataSource == null) {
//            // 加载数据源
//            FlexDataSource flexDataSource = FlexGlobalConfig.getDefaultConfig().getDataSource();
//            HikariDataSource newDataSource = getTenantDataSource(tenant);
//
//            flexDataSource.addDataSource(key, newDataSource);
//            DataSourceKey.use(key, () -> UaaDDL.createTables(tenant.getTenantname()));
//        }
//
//        return key;
//    }

//    public static HikariDataSource getTenantDataSource(Tenant tenant) {
//        HikariDataSource ret = new HikariDataSource();
//        String dbUrl = tenant.getDbUrl();
//        if(StrUtil.isBlank(dbUrl)) {
//            String url = SpringUtil.getProperty("spring.datasource.url");
//            String username = SpringUtil.getProperty("spring.datasource.username");
//            String password = SpringUtil.getProperty("spring.datasource.password");
//            String params = "?serverTimezone=UTC&createDatabaseIfNotExist=true";
//            String jdbcUrl = StrKit.cutInTwo(url, '?', false)[0];
////            String databaseName = jdbcUrl.substring(jdbcUrl.lastIndexOf('/') + 1);
//            String databaseName = tenant.getTenantname();
//            if(StrUtil.isBlank(databaseName)) throw new RuntimeException("租户名不能为空");
//
//            jdbcUrl = jdbcUrl.substring(0, jdbcUrl.lastIndexOf('/') + 1) + databaseName + params;
//            ret.setJdbcUrl(jdbcUrl);
//            ret.setUsername(username);
//            ret.setPassword(password);
//        } else {
//            ret.setJdbcUrl(dbUrl);
//            ret.setUsername(tenant.getDbUsername());
//            ret.setPassword(tenant.getDbPassword());
//        }
//
//        return ret;
//    }

//    @Override
//    public List<String> getFinalActionPermis(Tenant tenant) {
//        return actionPermiService.getFinalActionPermis(tenant);
//    }

//    public Tenant getByTenantname(String tenantname) {
//        return getOne(query().where(TENANT.TENANTNAME.eq(tenantname)));
//    }
}
